

#pragma once

#include "../DefinesCore.hpp"
#include <string>
#include <list>

CYBERTRON_BEGIN

class SocketUdpServerImpl;

// Note: one port can only be listened by one process!
class SocketUdpServer
{
public:
	CybertronCoreAPI SocketUdpServer();
	CybertronCoreAPI virtual ~SocketUdpServer();

	CybertronCoreAPI bool initialize(
		int port, 
		// -1 means every message will be cached.
		int numMaximalMessageCache = -1);
	CybertronCoreAPI void clear();

	CybertronCoreAPI void takeAwayMessages(
		std::list<std::string>& messages);
	CybertronCoreAPI void send(
		const std::string& ip,
		int port,
		const void* pData,
		size_t len);

private:
	SocketUdpServer(const SocketUdpServer&);
	SocketUdpServer& operator = (const SocketUdpServer&);

private:
	SocketUdpServerImpl* mpImpl;
};


class SocketUdpRawDataServerImpl;

// Note: one port can only be listened by one process!
class SocketUdpRawDataServer
{
public:
    CybertronCoreAPI SocketUdpRawDataServer();
    CybertronCoreAPI virtual ~SocketUdpRawDataServer();

    CybertronCoreAPI bool initialize(
        int port,
        // -1 means every message will be cached.
        int numMaximalMessageCache = -1);
    CybertronCoreAPI void clear();
    CybertronCoreAPI void clearBuffer();

    // user need to release the pData with delete[]
    CybertronCoreAPI void takeAwayMessage(
        char*& pData, int& len);
    CybertronCoreAPI void takeAwayTopMessageAndClear(
        char*& pData, int& len);
    CybertronCoreAPI void send(
        const std::string& ip,
        int port,
        const void* pData,
        size_t len);

private:
    SocketUdpRawDataServer(const SocketUdpRawDataServer&);
    SocketUdpRawDataServer& operator = (const SocketUdpRawDataServer&);

private:
    SocketUdpRawDataServerImpl* mpImpl;
};

CYBERTRON_END
